package com.bjsxt.controller.doctor;

import com.bjsxt.aspectj.annotation.Log;
import com.bjsxt.aspectj.enums.BusinessType;
import com.bjsxt.constants.Constants;
import com.bjsxt.controller.BaseController;
import com.bjsxt.domain.Dept;
import com.bjsxt.domain.Patient;
import com.bjsxt.domain.Registration;
import com.bjsxt.dto.PatientDto;
import com.bjsxt.dto.RegistrationDto;
import com.bjsxt.dto.RegistrationFormDto;
import com.bjsxt.dto.RegistrationQueryDto;
import com.bjsxt.service.DeptService;
import com.bjsxt.service.PatientService;
import com.bjsxt.service.RegistrationService;
import com.bjsxt.service.SchedulingService;
import com.bjsxt.utils.IdGeneratorSnowflake;
import com.bjsxt.utils.ShiroSecurityUtils;
import com.bjsxt.vo.AjaxResult;
import com.bjsxt.vo.DataGridView;
import com.fasterxml.jackson.databind.ser.Serializers;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.Collections;
import java.util.List;

/**
 * @author:liao
 * @Description:TODO
 * @date:2021/1/15
 */
@RestController
@RequestMapping("doctor/registration")
public class RegistrationController extends BaseController {

    @Autowired
    private DeptService deptService;

    @Reference
    private SchedulingService schedulingService;

    @Reference
    private PatientService patientService;

    @Reference
    private RegistrationService registrationService;

    /**
     * 根据条件<h1>科室id、排班日期、排班类型(门诊、急诊)、排班时间段<h1/>查询有号的部门
     * TODO 逻辑
     *      1.根据条件查询出有号的科室id集合
     *      2.根据查询出的科室id集合查询科室信息
     */
    @GetMapping("listDeptForScheduling")
    @HystrixCommand
    public AjaxResult listDeptForScheduling(RegistrationQueryDto registrationQueryDto){
        Long deptId = registrationQueryDto.getDeptId();// 部门id
        String schedulingDay = registrationQueryDto.getSchedulingDay();// 排班日期
        String schedulingType = registrationQueryDto.getSchedulingType();// 排班类型 1门诊 2急诊
        String subsectionType = registrationQueryDto.getSubsectionType(); // 排班时间段 1上午 2下午 3晚上
       //TODO 1.根据条件查询出有号的科室id集合
        List<Long> deptIds = this.schedulingService.queryHasSchedulingDeptIds(deptId,schedulingDay,schedulingType,subsectionType);
        //TODO 2.根据查询出的科室id集合查询科室信息
        if (null==deptIds||deptIds.size()==0){
            // 查出的科室id为空 表示所有的科室都没有号了
            return AjaxResult.success(Collections.EMPTY_LIST);
        }else {
            List<Dept> deptList = this.deptService.listDeptByDeptIds(deptIds);
            return AjaxResult.success(deptList);
        }
    }

    /**
     * 根据身份证号查询患者信息
     */
    @GetMapping("getPatientByIdCard/{idCard}")
    @HystrixCommand
    public AjaxResult getPatientByIdCard(@PathVariable String idCard){
        Patient patient = this.patientService.getPatientByIdCard(idCard);
        if (null==patient){
            return AjaxResult.fail("身份证号【"+idCard+"】不存在，请在下面新建患者信息");
        }else {
            return AjaxResult.success(patient);
        }
    }

    /**
     * 添加挂号信息
     */
    @PostMapping("addRegistration")
    @Log(title = "添加挂号信息",businessType = BusinessType.INSERT)
    @HystrixCommand
    public AjaxResult addRegistration(@RequestBody RegistrationFormDto registrationFormDto){
        PatientDto patientDto = registrationFormDto.getPatientDto();// 获取患者信息
        RegistrationDto registrationDto = registrationFormDto.getRegistrationDto();// 获取挂号信息
        Patient patient = null;
        // 判断患者id是否为空 如果患者id为空则表示患者是第一次来医院
        // 需要将患者信息插入到数据库中
        if (StringUtils.isBlank(patientDto.getPatientId())){
            // 设置操作用户
            patientDto.setSimpleUser(ShiroSecurityUtils.getCurrentSimpleUser());
            // 设置主键 使用雪花算法
            patientDto.setPatientId(IdGeneratorSnowflake.generatorIdWithProfix("HZ"));
            // 插入患者信息到数据库中
            patient =  patientService.addPatient(patientDto);
        }else {
            // 因为前端传过来的患者信息有可能是不全的所以我们要
            // 根据患者id从数据库中查询患者信息
           patient = patientService.getPatientById(patientDto.getPatientId());
        }
        if (null==patient){
            return AjaxResult.fail("当前患者id不存在 请确认后再提交");
        }

        // 保存挂号信息
        // 生成挂号信息主键
        registrationDto.setRegistrationId(IdGeneratorSnowflake.generatorIdWithProfix("GH"));
        //设置患者id
        registrationDto.setPatientId(patient.getPatientId());
        // 设置患者名称
        registrationDto.setPatientName(patient.getName());
        // 每当患者挂号科室一次 对应科室的挂号编号就要+1 因为挂号编号在科室表中
        // 所以我们要获取科室表的信息
        Dept dept = this.deptService.getOne(Long.valueOf(registrationDto.getDeptId()));
        // 设置挂号编号+1
        registrationDto.setRegistrationNumber(dept.getRegNumber()+1);
        // 设置挂号日期 为了防止取到日期之外的时间 所以此处我们只取前10位
        registrationDto.setVisitDate(registrationDto.getVisitDate().substring(0,10));
        // 设置操作人
        registrationDto.setSimpleUser(ShiroSecurityUtils.getCurrentSimpleUser());
        // 添加挂号信息
        this.registrationService.addRegistration(registrationDto);

        // 每当患者挂号科室一次 对应科室的挂号编号就要+1
        // 修改对应科室挂号编号
        this.deptService.updateDeptRegNumber(dept.getDeptId(),dept.getRegNumber()+1);

        // 返回挂号编号
        return AjaxResult.success("",registrationDto.getRegistrationId());
    }

    /**
     * 收费
     * TODO 收费其实就是更改挂号单的状态
     */
    @PostMapping("collectFee/{regId}")
    @HystrixCommand
    public AjaxResult collectFee(@PathVariable String regId){
        // 根据挂号单id查询挂号单信息
        Registration registration = registrationService.queryRegistrationByRegId(regId);
        if (null==registration){
            return AjaxResult.fail("挂号单【"+regId+"】对应的挂号信息不存在,请核对后再进行收费");
        }
        // 检验挂号单的状态 如果挂号单状态不是未收费 则不能进行收费
        if (!registration.getRegistrationStatus().equals(Constants.REG_STATUS_0)){
            return AjaxResult.fail("挂号单【"+regId+"】不是未收费状态 不能进行收费");
        }
        // 更改挂号单的状态为待就诊
        registration.setRegistrationStatus(Constants.ORDER_STATUS_1);
        return AjaxResult.toAjax(this.registrationService.updateRegistrationById(registration));
    }

    /**
     * 分页查询患者挂号信息
     */
    @GetMapping("queryRegistrationForPage")
    public AjaxResult queryRegistrationForPage(RegistrationDto registrationDto){
        // 分页查询挂号信息
        DataGridView dataGridView = this.registrationService.queryRegistrationForPage(registrationDto);
        return AjaxResult.success("查询成功",dataGridView.getData(),dataGridView.getTotal());
    }

    /**
     * 根据挂号单id作废挂号单
     * TODO 修改挂号单的状态为作废 只有未收费的挂号单才能进行作废
     */
    @PostMapping("doInvalid/{regId}")
    public AjaxResult doInvalid(@PathVariable String regId){
        // 当前挂号单id对应的挂号单信息
        Registration registration = registrationService.queryRegistrationByRegId(regId);
        // 校验是否存在该挂号信息
        if (null==registration){
            return AjaxResult.fail("没有与【"+regId+"】对应的挂号信息,请核对后再进行作废");
        }
        // 校验挂号单的状态 只有为收费的挂号单才能进行作废
        if (!registration.getRegistrationStatus().equals(Constants.REG_STATUS_0)){
            return AjaxResult.fail("挂号单【"+regId+"】不是未收费状态 不能进行作废");
        }
        registration.setRegistrationStatus(Constants.REG_STATUS_5);
        this.registrationService.updateRegistrationById(registration);
        return AjaxResult.success("作废成功!");
    }

    /**
     * 退号
     * TODO 修改挂号单的状态 只有待就诊的挂号单才能进行退号
     */
    @PostMapping("doReturn/{regId}")
    public AjaxResult doReturn(@PathVariable String regId){
        // 当前挂号单id对应的挂号单信息
        Registration registration = registrationService.queryRegistrationByRegId(regId);
        // 校验是否存在该挂号信息
        if (null==registration){
            return AjaxResult.fail("没有与【"+regId+"】对应的挂号信息,请核对后再进行作废");
        }
        // 校验挂号单的状态 只有为待就诊的挂号单才能进行退号
        if (!registration.getRegistrationStatus().equals(Constants.REG_STATUS_1)){
            return AjaxResult.fail("挂号单【"+regId+"】不是待就诊状态 不能进行退号");
        }
        registration.setRegistrationStatus(Constants.REG_STATUS_4);
        this.registrationService.updateRegistrationById(registration);
        return AjaxResult.success("退号成功!");
    }



}
